package com.hyj.serve.manage.entity.firewall;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.hyj.serve.manage.enums.IPFamilyEnum;
import com.hyj.serve.manage.enums.FirewallAction;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.util.List;

/**
 * @author HeYuJie
 * @date 2022/6/2
 *
 * 对应/etc/firewalld/zones/public.xml文件
 *
 */
@Slf4j
@Data
public class FirewallRule extends RuleItem {

    public static final String TAG_NAME = "rule";
    private String type = TAG_NAME;

    // 描述
    private String description;
    // 地址版本（ipv4/ipv6）
    private IPFamilyEnum family = IPFamilyEnum.ipv4;

    // 动作
    private FirewallAction action = FirewallAction.ACCEPT;

    // 项目
    private PortRule port;
    private SourceRule source;
    private ServiceRule service;

    public IPFamilyEnum getFamily() {
        return ObjectUtil.defaultIfNull(family, IPFamilyEnum.ipv4);
    }

    @Override
    public String serializeXml(String prefix) {
        if(port == null && source == null && service == null){
            return null;
        }

        StringBuilder sb = new StringBuilder();
        sb.append(prefix).append("<"+ TAG_NAME +" family=\"").append(family).append("\">\n");
        if(StrUtil.isNotEmpty(this.description)){
            sb.append(prefix).append("  <description>").append(this.description).append("</description>\n");
        }
        sb.append(prefix).append("  <").append(this.action.getCode()).append("/>\n");


        if(port != null){
            sb.append(port.serializeXml(prefix+"  ")).append("\n");
        }
        if(source != null){
            sb.append(source.serializeXml(prefix+"  ")).append("\n");
        }
        if(service != null){
            sb.append(service.serializeXml(prefix+"  ")).append("\n");
        }

        return sb.append(prefix).append("</"+ TAG_NAME +">").toString();
    }

    public static FirewallRule deserializeXml(String xml){
        if(StrUtil.isEmpty(xml)){
            return null;
        }
        try {
            Document document = DocumentHelper.parseText(xml);
            Element rootElement = document.getRootElement();
            return deserializeXml(rootElement);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static FirewallRule deserializeXml(Element xml){
        if(xml == null || !xml.getName().equalsIgnoreCase(TAG_NAME)){
            return null;
        }
        try {
            FirewallRule rule = new FirewallRule();

            String family = xml.attributeValue("family");
            rule.family = IPFamilyEnum.valueOf(family);

            List<Element> elements = xml.elements();

//            Map<String, RuleItem> items = new HashMap<>(elements.size());
//            rule.items = items;

            for (Element child : elements) {
                String childName = child.getName().toLowerCase();

                switch (childName) {
                    case "drop":
                    case "accept":
                        rule.action = FirewallAction.valueOfCode(childName);
                        break;
                    case "description":
                        rule.description = child.getTextTrim();

                        break;
                    case PortRule.TAG_NAME:
                        rule.port = PortRule.deserializeXml(child);

                        break;
                    case SourceRule.TAG_NAME:
                        rule.source = SourceRule.deserializeXml(child);

                        break;
                    case ServiceRule.TAG_NAME:
                        rule.service = ServiceRule.deserializeXml(child);
                        break;
                }
            }

            return rule;
        } catch (Exception e){
            log.error("解析"+xml.getName()+"错误", e);
            return null;
        }
    }


    public static void main(String[] args) throws DocumentException {
        String xml = "<zone>\n" +
                "  <short>Public</short>\n" +
                "  <description>For use in public areas. You do not trust the other computers on networks to not harm your computer. Only selected incoming connections are accepted.</description>\n" +
                "  <source address=\"192.168.0.0/22\"/>\n" +
                "  <service name=\"ssh\"/>\n" +
                "  <service name=\"dhcpv6-client\"/>\n" +
                "  <service name=\"http\"/>\n" +
                "  <port protocol=\"tcp\" port=\"306\"/>\n" +
                "  <rule family=\"ipv4\">\n" +
                "    <source address=\"192.168.0.142\"/>\n" +
                "    <port protocol=\"tcp\" port=\"80\"/>\n" +
                "    <accept/>\n" +
                "  </rule>\n" +
                "  <rule family=\"ipv4\">\n" +
                "    <source address=\"192.168.0.142\"/>\n" +
                "    <port protocol=\"tcp\" port=\"80\"/>\n" +
                "    <drop/>\n" +
                "  </rule>\n" +
                "</zone>";

        FirewallZone firewallZone = FirewallZone.deserializeXml(xml);
        System.out.println(firewallZone.serializeXml(""));
    }
}
